国防科技大学 编译原理 第13讲 语法分析——自下而上分析4
课程主页:
https://www.icourse163.org/course/NUDT-1003101005?tid=1460976445
这次回顾第13讲:语法分析——自下而上分析4。
第13讲 更强的$LR$分析
一个非$LR(0)$文法
考虑文法$G(S’)$:
该文法的识别活前缀的DFA以及$LR(0)$项目集规范族如下:
$I_1,I_2$和$I_9$都含有“移进-归约”冲突:
但实际上,我们可以通过其他信息来判断移进规约,回顾Follow集合:
计算可得:
对于状态$I_1$,如果当前的单词是$\sharp$,那么使用规约;如果是$+$,那么使用移进。
$SLR(1)$冲突解决办法
冲突解决办法
假定一个$LR(0)$规范族含有如下的一个项目集(状态)
$\text{FOLLOW}(A)$和$\text{FOLLOW}(B)$的交集为$\varnothing$,且不包含$b$
当状态$I$面临任何输入符号$a$时,可以:
- 若$a=b$,则移进;
- 若$a∈\mathrm{FOLLOW}(A)$,用产生式$A→α$进行归约;
- 若$a∈\mathrm{FOLLOW}(B)$,用产生式$B→α$进行归约;
- 此外,报错。
$SLR(1)$冲突解决办法
对之前的方法进行推广:
假定$LR(0)$规范族的一个项目集
如果集合
两两不相交(包括不得有两个$\text{FOLLOW}$集合有$\sharp$),则当状态I面临任何输入符号$a$ 时:
- 若$a$是某个$a_i,i=1,2,…,m$,则移进;
- 若$a∈\mathrm{FOLLOW}(B_i),i=1,2,…,n$,则用产生式$B_i→α$进行归约;
- 此外,报错。
这种方法被称为$SLR(1)$解决办法,其中:S-Simple,1-最多向前看一个单词
$SLR(1)$分析表的构造
构造SLR(1)分析表的方法
- 把$G$拓广为$G′$
- 对$G′$构造
- $LR(0)$项目集规范族$C$
- 活前缀识别自动机的状态转换函数$GO$
- 使用$C$和$GO$,构造$SLR$分析表
- 令每个项目集$I_k$的下标$k$作为分析器的状态,包含项目$S′→•S$的集合$I_k$的下标$k$为分析器的初态。
- 构造分析表的$\mathrm{ACTION}$和$\mathrm{GOTO}$子表
$SLR(1)$分析表的$\text{ACTION}$和$\text{GOTO}$子表构造
算法流程:
- 若项目$A→α•aβ$属于$I_k$且$\mathrm{GO}(I_k,a)=I_j$,$a$为终结符,则置$\mathrm{ACTION}[k,a]$为$s_j$;
- 若项目$A→α•$属于$I_k$,那么,对任何终结符$a∈\mathrm{FOLLOW}(A)$,置$\mathrm{ACTION}[k,a]$为$r_j$;其中,假定
$A→α$为文法$G′$的第$j$个产生式; - 若项目$S′→S•$属于$I_k$,则置$\mathrm{ACTION}[k,\sharp]$为$\mathrm{acc}$;
- 若$\mathrm{GO}(I_k,A)=I_j$,$A$为非终结符,则置$\mathrm{GOTO}[k,A]=j$;
- 分析表中凡不能用规则1至4填入信息的空白格均置上“报错标志” 。
$SLR(1)$和$LR(0)$分析表构造方法的对比
$SLR(1)$文法
- 按上述方法构造出的$\mathrm{ACTION}$与$\mathrm{GOTO}$表如果不含多重入口,则称该文法为$SLR(1)$文法。
- 使用$SLR$表的分析器叫做一个$SLR$分析器。
- 每个$SLR(1)$文法都是无二义的。但也存在许多无二义文法不是$SLR(1)$的。
- $LR(0) ⊂ SLR(1) ⊂ $无二义文法
SLR(1)分析表构造示例
依然考虑之前的拓广文法$G(S’)$:
$\mathrm{ACTION}$和$\mathrm{GOTO}$子表如下:
一个非SLR(1)文法
例子
考虑文法$G(S’)$:
识别活前缀的DFA以及$LR(0)$项目集规范族如下:
考虑状态$I_2$:
这说明该文法不是$SLR(1)$。
但是注意到该文法
- 没有以“$R=$”为前缀的规范句型
- 有以“$\star R=$”为前缀的规范句型
当状态栈的栈顶为$2$时,如果符号栈栈顶为$L$,并且$L$之前没有$\star$,那么不能使用移入规约。
SLR冲突消解存在的问题
$SLR$在方法中,如果项目集$I_i$含项目$A→α•$而且下一输入符号$a∈\mathrm{FOLLOW}(A)$,则状态$i$面临$a$时,可选用“用$A→α$归约”动作
但在有些情况下,当状态$i$显现于栈顶时,当前单词是$a$,栈里的活前缀$βα$未必允许把$α$归约为$A$,因为可能根本就不存在一个形如“$βAa$”的规范句型
在这种情况下,用“$A→α$”归约不一定合适
即$\mathrm {FOLLOW}$集合提供的信息太泛
LR(1)分析表的构造
构造LR(1)分析表的方法
- 把$G$拓广为$G′$
- 对$G′$构造$LR(1)$项目集规范族$C$和活前缀识别自动机的状态转换函数$\mathrm{GO}$
- 使用$C$和$\mathrm{GO}$,构造$LR(1)$分析表
$LR(k)$项目
$LR(k)$项目:扩展$LR(0)$项目,附带有$k$个终结符
$a_1a_2\ldots a_k$称为向前搜索符串(或展望串)。
归约项目$[A→α•,a_1a_2…a_k]$的意义:当它所属的状态呈现在栈顶且后续的$k$个输入符号为$a_1a_2…a_k$时,才可以把栈顶上的$α$归约为$A$
对于任何移进或待约项目$[A→α•β, a_1a_2…a_k]$,$β≠ε$,搜索符串$a_1a_2…a_k$没有直接作用
有效项目
形式上我们说一个$LR(1)$项目$[A→α•β, a]$对于活前缀$γ$是有效的,如果存在规范推导
其中,
- $γ=δα$
- $a$是$ω$的第一个符号,或者$a$为$\sharp$而$ω$为$ε$
有效项目的性质
- $[A→α•Bβ, a]$对活前缀$γ=δα$是有效的,则对于每个形如$B→ξ$的产生式, 对任何$b∈\mathrm{FIRST}(βa)$,$[B→•ξ, b]$对$γ$也是有效的。
证明:
若项目$[A→α•Bβ, a]$对$γ=δα$有效, 则有
因为
所以
若$B→ξ$是产生式,则
因此项目$[B→•ξ, b]$对$γ=δα$是有效的。
$LR(1)$项目集规范族
- 构造$LR(1)$项目集规范族
- 闭包函数$\mathrm{CLOSURE}$
- 转换函数$\mathrm{GO}$
项目集的闭包$\mathrm{CLOSURE}$
假定$I$是文法$G′$的任一项目集,定义和构造$I$的闭包$\mathrm{CLOSURE}(I)$如下:
- $I$的任何项目都属于$\mathrm{CLOSURE}(I)$。
- 若项目$[A→α•Bβ, a]$属于$\mathrm{CLOSURE}(I)$,$B→ξ$是一个产生式,那么,对于$\mathrm{FIRST}(βa)$中的每个终结符$b$,如果$[B→•ξ, b]$原来不在$\mathrm{CLOSURE}(I)$中,则把它加进去。
- 重复执行步骤2,直至$\mathrm{CLOSURE}(I)$不再增大为止。
项目集的转换函数$\mathrm{GO}$
令$I$是一个项目集,$X$是一个文法符号,函数$\mathrm{GO}(I,X)$定义为:
其中
LR(1)项目集规范族的构造算法
- BEGIN
- $C:=\lbrace \mathrm{CLOSURE}( { [S′→•S,\sharp] } ) \rbrace $;
- REPEAT
- FOR $C$中每个项目集$I$和$G′$的每个符号$X$ DO
- IF $\mathrm{GO}(I,X)$非空且不属于$C$,THEN
- 把$\mathrm{GO}(I,X)$加入$C$中
- IF $\mathrm{GO}(I,X)$非空且不属于$C$,THEN
- FOR $C$中每个项目集$I$和$G′$的每个符号$X$ DO
- UNTIL $C$不再增大
- END
$LR(1)$分析表的构造算法
- 把$G$拓广为$G′$
- 对$G′$构造$LR(1)$项目集规范族$C$和活前缀识别自动机的状态转换函数$\mathrm{GO}$
- 使用$C$和$\mathrm{GO}$,构造$LR(1)$分析表
- 令每个$I_k$的下标$k$为分析表的状态,令含有$[S′→•S,\sharp]$的$I_k$的$k$为分析器的初态
- 构造$LR(1)$分析表的$\mathrm{ACTION}$和$\mathrm{GOTO}$子表
$LR(1)$分析表的$\mathrm{ACTION}$和$\mathrm{GOTO}$子表构造
- 若项目$[A→α•aβ, b]$属于$I_k$且$\mathrm{GO}(I_k, a)=I_j$, $a$为终结符,则置$\mathrm{ACTION}[k, a]$为“$s_j$”。
- 若项目$[A→α•,a]$属于$I_k$,则置$\mathrm{ACTION}[k, a]$为“$r_j$”;其中假定$A→α$为文法$G′$的第$j$个产生式。
- 若项目$[S′→S•,\sharp]$属于$I_k$,则置$\mathrm{ACTION}[k, \sharp]$为“acc”。
- 若$\mathrm{GO}(I_k,A)=I_j$,则置$\mathrm{GOTO}[k, A]=j$。
- 分析表中凡不能用规则1至4填入信息的空白栏均填上“出错标志”。
$LR(1)$和$SLR(1)$分析表构造方法的对比
$LR(1)$分析表和$LR(1)$文法
- 按上述算法构造的分析表,若不存在多重定义的入口(即,动作冲突)的情形,则称它是文法$G$的一张规范的$LR(1)$分析表。
- 具有规范的$LR(1)$分析表的文法称为一个$LR(1)$文法。
- 使用$LR(1)$分析表的分析器叫做一个规范的LR分析器。
- $LR(1)$状态比$SLR(1)$多
- $LR(0) ⊂ SLR(1) ⊂ LR(1) ⊂ $无二义文法
$LR(1)$分析表构造示例
$LR(1)$分析表的构造
考虑拓展文法$G(S’)$:
识别活前缀的DFA:
$LR(1)$分析表:
$LR(1)$分析示例
利用文法$G(S’)$:
以及$LR(1)$分析表:
分析$abab$: